package case23

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"time"
)

func Test() {
	fmt.Println("🎯示例二十三：操作新增、修改、删除")

	db, err := mysqlConnect()
	if err != nil {
		log.Println("mysql connect err:", err)
		return
	}
	fmt.Println(db)

	if err := db.AutoMigrate(&UserCase23{}); err != nil {
		log.Println("自动创建表结构体失败：", err)
		return
	}

	// 操作工具
	oper := NewOperateUtil(db)
	fmt.Println(oper)

	// 新增数据
	////表结构体
	//u := UserCase23{UserName: "李宽", Sex: false, Hw: 0.34, Height: 12.21, Weight: 14.21, Birthday: time.Now()}
	//oper.Add(&u)
	//fmt.Println(u.ID, u)
	////方式一(表结构体-数组)
	//uArr2 := []UserCase23{
	//	{UserName: "李啸", Sex: false, Hw: 0.34, Height: 12.21, Weight: 14.21, Birthday: time.Now()},
	//	{UserName: "李框", Sex: true, Hw: 0.44, Height: 17.71, Weight: 14.21, Birthday: time.Now()},
	//	{UserName: "李款", Sex: false, Hw: 0.54, Height: 15.51, Weight: 14.21, Birthday: time.Now()},
	//}
	//oper.Add(&uArr2)
	//fmt.Println(uArr2)

	//// 新增单条数据
	////map匿名结构体
	//addMap1 := map[string]interface{}{
	//	"UserName": "李匡",
	//	"Sex":      true,
	//	"Hw":       nil,
	//	"Height":   18.21,
	//	"Weight":   19.01,
	//	"Birthday": time.Now(),
	//}
	//amid1, _ := oper.AddTo(UserCase23{}, &addMap1)
	//fmt.Println("map新增返回id:", amid1, addMap1)
	//
	////结构体
	//var auobj1 = Case23User{UserName: "刘浩3", Sex: true, Hw: 0.34, Height: 12.21, Weight: 66.21, Birthday: time.Now()}
	//aid1, _ := oper.AddTo(UserCase23{}, &auobj1)
	//fmt.Println("struct新增返回id:", aid1, auobj1)
	////匿名结构体
	//obj1 := struct {
	//	ID       int       `json:"id"`
	//	UserName string    `json:"user_name"`
	//	Sex      bool      `json:"sex"`
	//	Age      int       `json:"age"`
	//	Hw       float64   `json:"hw"`
	//	Height   float64   `json:"height"`
	//	Weight   float64   `json:"weight"`
	//	Remark   string    `json:"remark"`
	//	Birthday time.Time `json:"birthday"` //出生年月日
	//}{
	//	UserName: "刘豪", Sex: true, Hw: 6.3, Height: 17.21, Weight: 45.21, Birthday: time.Now(),
	//}
	//aid2, _ := oper.AddTo(UserCase23{}, &obj1)
	//fmt.Println("匿名结构体struct新增返回id:", aid2, obj1)

	// 批量新增多条
	////map匿名结构体-数组
	//addMap2 := []map[string]interface{}{
	//	{
	//		"UserName": "李匡朔",
	//		"Sex":      false,
	//		"Age":      18,
	//		"Hw":       23.01,
	//		"Height":   18.21,
	//		"Weight":   19.01,
	//		"Birthday": time.Now(),
	//	},
	//	{
	//		"UserName": "李匡烁",
	//		"Sex":      false,
	//		"Age":      21,
	//		"Hw":       23.01,
	//		"Height":   18.21,
	//		"Weight":   19.01,
	//		"Birthday": time.Now(),
	//	},
	//}
	//oper.AddToBatch(UserCase23{}, addMap2, 0)
	//fmt.Println("可以返回id", addMap2)

	//结构体-数组
	arrobj1 := []struct {
		ID       int       `json:"id"`
		UserName string    `json:"user_name"`
		Sex      bool      `json:"sex"`
		Age      int       `json:"age"`
		Hw       float64   `json:"hw"`
		Height   float64   `json:"height"`
		Weight   float64   `json:"weight"`
		Remark   string    `json:"remark"`
		Birthday time.Time `json:"birthday"` //出生年月日
	}{
		{UserName: "刘浩", Sex: true, Hw: 0.34, Height: 12.21, Weight: 66.21, Birthday: time.Now()},
		{UserName: "刘郝", Sex: false, Hw: 0.56, Height: 18.21, Weight: 77.21, Birthday: time.Now()},
		{UserName: "刘豪", Sex: true, Hw: 6.3, Height: 17.21, Weight: 45.21, Birthday: time.Now()},
	}
	oper.AddToBatch(UserCase23{}, arrobj1, 0)
	fmt.Println("可以返回id", arrobj1)

	//////方式二(map匿名结构体)
	////方式二()

	//方式三(匿名结构体)

	//aobj1 := arrobj1[0:1] //取第一个元素对象
	//obj1 := aobj1[0]
	//fmt.Println(obj1)
	//aid1, _ := oper.AddTo(UserCase23{}, &obj1)
	//fmt.Println("返回id:", aid1, obj1)
	//
	//arrobj2 := arrobj1[1:3] //取从第二个元素和第三个元素
	//fmt.Println(arrobj2)

	//// 操作修改
	//uMap2 := map[string]interface{}{
	//	"UserName": "李小四",
	//	"Sex":      false,
	//	"Age":      15,
	//}
	//res, err := oper.Edit(&UserCase23{}, 5, uMap2)
	//fmt.Println(res)

	//// 操作修改
	//uMap3 := map[string]interface{}{
	//	"Age": 16,
	//}
	////条件
	//condition1 := map[string]interface{}{
	//	"id": 5,
	//}
	//res, err := oper.EditByConditions(&UserCase23{}, condition1, uMap3)
	//fmt.Println(res)

	// 操作删除
	//res, err := oper.SoftDeleteByID(&UserCase23{}, 5)
	//fmt.Println(res)

	findList()
}

func findList() {
	db, err := mysqlConnect()
	if err != nil {
		fmt.Println("mysql connect err:", err)
		return
	}

	uArr2 := []UserCase23{}
	db.Find(&uArr2)
	for _, u := range uArr2 {
		fmt.Printf("u: %+v\n", u)
	}
}

// 初始化连接
func mysqlConnect() (*gorm.DB, error) {
	url := "root:123456@tcp(127.0.0.1:3306)/case1?charset=utf8mb4&parseTime=True&loc=Local"

	// 配置自定义 Logger 打印sql日志
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢 SQL 阈值
			LogLevel:                  logger.Info, // 可以设置为不同级别 Silent-不打印任何日志 Error-只打印错误日志 Warn-打印慢查询和错误 Info-打印慢查询和错误
			IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
			Colorful:                  true,        // 彩色打印
		},
	)

	db, err := gorm.Open(mysql.Open(url), &gorm.Config{
		Logger: newLogger, // 设置 Logger
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true, // 关闭默认，使用表名
		},
	})
	if err != nil {
		return nil, fmt.Errorf("mysql connect err: %v", err)
	}

	sqlDB, err := db.DB()
	if err != nil {
		panic("failed to get sql.DB")
	}

	// 配置连接池
	// 最大空闲连接数 - 应该小于最大打开连接数
	sqlDB.SetMaxIdleConns(20)
	// 最大打开连接数 - 根据应用负载和MySQL配置调整
	sqlDB.SetMaxOpenConns(100)
	// 连接最大生命周期 - 小于MySQL的wait_timeout设置
	sqlDB.SetConnMaxLifetime(5 * time.Minute)
	// 空闲连接最大存活时间
	sqlDB.SetConnMaxIdleTime(10 * time.Minute)

	return db, nil
}

// 定义结构体
type UserCase23 struct {
	ID         int       `gorm:"primarykey;autoIncrement"`
	UserName   string    `gorm:"type:varchar(50);not null"`
	Sex        bool      `gorm:"type:tinyint(1);default:true"`
	Age        int       `gorm:"type:int(4);default:1"`
	Hw         float64   `gorm:"type:float"`
	Height     float64   `gorm:"type:double"`
	Weight     float64   `gorm:"type:decimal(10,2)"`
	Remark     string    `gorm:"type:text"`
	Birthday   time.Time `gorm:"type:date"`                    //出生年月日
	CreateTime time.Time `gorm:"type:datetime;autoCreateTime"` //自动设置创建时间
}

// 非表结构体
type Case23User struct {
	ID       int       `json:"id"`
	UserName string    `json:"user_name"`
	Sex      bool      `json:"sex"`
	Age      int       `json:"age"`
	Hw       float64   `json:"hw"`
	Height   float64   `json:"height"`
	Weight   float64   `json:"weight"`
	Remark   string    `json:"remark"`
	Birthday time.Time `json:"birthday"` //出生年月日
}
